﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.Threading;
using AircraftBattleServer;
using System.Windows.Controls;

namespace AircraftBattleClient
{
    public class BackgroundWorker
    {
        MainWindow mainWin;
        int craftId;
        static GameEngineServiceClient clt = new GameEngineServiceClient();

        public BackgroundWorker(MainWindow w, string username)
        {
            this.mainWin = w;
            this.craftId = w.craftId;
        }

        public void Run()
        {
            while (true)
            {
                // Background thread can only access the UI thread via
                // the UI thread's dispatcher
                this.mainWin.Dispatcher.Invoke(DispatcherPriority.Normal,
                    new Action(() => { UpdateCanvas(); }));
                Thread.Sleep(50);
            }
        }

        public void UpdateCanvas()
        {
            MapData mapdata = clt.GetMapData();

            // Check Game End
            CheckGameEnd(mapdata);

            // update according to mapdata
            foreach (Aircraft ac in mapdata.aircrafts.Values)
            {
                // Check for whether died
                if (!ac.alive)
                {
                    BattleLib.Die(this.mainWin.cnvsMain, ac);
                    if (ac.id == craftId) this.mainWin.alive = false;
                    continue;
                }
                
                Image img = (Image)this.mainWin.FindName(ClientUtility.GetAircraftImageName(ac.id));

                // Update positions
                if (ac.id == craftId)
                {
                    MyPoint p = new MyPoint();
                    p.x = Canvas.GetLeft(img);
                    p.y = Canvas.GetTop(img);
                    bool changed = false;

                    if (p.x > 0 && this.mainWin.left == 1)
                    {
                        p = BattleLib.ChangeAircraftPosition(img, this.craftId, Direction.Left);
                        changed = true;
                    }
                    if (p.x + Constants.AircraftImageWidth < Constants.CanvasWidth && this.mainWin.right == 1)
                    {
                        p = BattleLib.ChangeAircraftPosition(img, this.craftId, Direction.Right);
                        changed = true;
                    }
                    if (p.y > 0 && this.mainWin.up == 1)
                    {
                        p = BattleLib.ChangeAircraftPosition(img, this.craftId, Direction.Up);
                        changed = true;
                    }
                    if (p.y + Constants.AircraftImageHeight < Constants.CanvasHeight && this.mainWin.down == 1)
                    {
                        p = BattleLib.ChangeAircraftPosition(img, this.craftId, Direction.Down);
                        changed = true;
                    }

                    if (changed) clt.SetPosition(craftId, p.x, p.y);
                } else {
                    BattleLib.SetPosition(img, ac.position.x, ac.position.y);
                    BattleLib.RotateImage(img, ac.angle - Constants.AircraftInitialAngle1);
                }
            }

            foreach (Missile m in mapdata.missiles)
            {
                Image img = (Image)this.mainWin.FindName(ClientUtility.GetMissileImageName(m.id));

                // create the missile if not exist
                if (img == null)
                {
                    img = BattleLib.CreateMissileImage(this.mainWin.cnvsMain, m.id, m.position);
                }

                BattleLib.SetPosition(img, m.position.x, m.position.y);
            }
        }

        private void CheckGameEnd(MapData mapdata)
        {
            if (mapdata.winer > 0 || this.mainWin.gameEnd)
            {
                this.mainWin.gameEnd = true; // stop event handler of the main window
                Thread.Sleep(2000); // wait until server finish the clearing
                GameEnd resDialog = new GameEnd(this.mainWin.me, mapdata.winer);
                Nullable<bool> dialogResult = resDialog.ShowDialog();

                if (dialogResult.Value)
                {
                    this.mainWin.ReturnBackToLounge();
                }
                else
                {
                    this.mainWin.Close();
                }
            }
        }
    }
}
